package com.sinevil.tcpTrans.utils;

import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ClassInfoList;
import io.github.classgraph.ScanResult;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Classname Reflections
 * @Description TODO
 * @Version 1.0.0
 * @Date 2025/3/9 22:06
 * @Created by sinevil
 */
public class ReflectionUtils {
    static String[] packageNames = {"com.sinevil"};

    // 扫描带有特定注解的类
    public static List<Class<?>> scanClassesWithAnnotation(Class<? extends Annotation> annotationClass, String... packageNames) {
        List<Class<?>> annotatedClasses = new ArrayList<>();
        try (ScanResult scanResult = new ClassGraph()
                .enableClassInfo()
                .enableAnnotationInfo()
                .acceptPackages(packageNames)
                .scan()) {
            ClassInfoList classInfoList = scanResult.getClassesWithAnnotation(annotationClass.getName());
            for (ClassInfo classInfo : classInfoList) {
                try {
                    Class<?> clazz = classInfo.loadClass();
                    annotatedClasses.add(clazz);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return annotatedClasses;
    }

    // 扫描带有特定注解的方法
    public static List<Method> scanMethodsWithAnnotation(Class<? extends Annotation> annotation, String... packageNames) {
        List<Method> annotatedMethods = new ArrayList<>();
        try (ScanResult scanResult = new ClassGraph()
                .enableMethodInfo()
                .enableAnnotationInfo()
                .acceptPackages(packageNames)
                .scan()) {
            // 获取所有带有方法注解的类信息
             ClassInfoList classInfoList = scanResult.getClassesWithMethodAnnotation(annotation.getName());
             for (ClassInfo classInfo : classInfoList) {
                 // 加载类（可能抛出ClassNotFoundException）
                 Class<?> clazz = classInfo.loadClass();
                annotatedMethods.addAll(getMethodsWithAnnotation(clazz, annotation));
             }
        }
        return annotatedMethods;
    }


    /**
     * 从类中获取带有特定注解的方法
     * @param clazz 类
     * @param annotationClass 注解
     * @return 方法列表
     */
    private static List<Method> getMethodsWithAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass) {
        List<Method> annotatedMethods = new ArrayList<>();
        // 获取类中所有声明的方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            // 检查方法是否被 @BackEvent 注解标记
            if (method.isAnnotationPresent(BackEvent.class)) {
                annotatedMethods.add(method);
            }
        }
        return annotatedMethods;
    }

    /**
     * 扫描带有特定注解的类
     * @param annotation 注解
     * @return 类列表
     */
    public static List<Class<?>> scanClassesWithAnnotation(Class<? extends Annotation> annotation) {
        return scanClassesWithAnnotation(annotation, packageNames);
    }

    /**
     * 扫描带有特定注解的方法
     * @param annotation 注解
     * @return 方法列表
     */
    public static List<Method> scanMethodsWithAnnotation(Class<? extends Annotation> annotation) {
        return scanMethodsWithAnnotation(annotation, packageNames);
    }

}